﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace SimplexEngine
{
    public class SceneManager
    {
        public SceneManager()
        {
            root_node = InternalCreateSceneNode("Simplex::SceneRoot");
        }

        public SceneNode RootNode { get { return root_node; } }
        protected SceneNode root_node;

        protected virtual Dictionary<String, SceneObject> GetSceneObjects(String type)
        {
            if (!scene_objects_by_type.ContainsKey(type))
                scene_objects_by_type.Add(type, new Dictionary<String, SceneObject>());

            return scene_objects_by_type[type];
        }

        public virtual void Update(GameTime game_time, Int64 frame_number)
        {
            root_node.Update(game_time, frame_number);
        }

        public virtual void Draw(Camera camera, RenderSystem render_system, int view_filter, GameTime game_time, Int64 frame_number)
        {
            view_filter &= camera.ViewFilter;
            root_node.Draw(render_system, view_filter, game_time, frame_number);
        }

        protected Dictionary<String, Dictionary<String, SceneObject>> scene_objects_by_type = new Dictionary<String, Dictionary<String, SceneObject>>();
        protected List<SceneObject> huge_objects = new List<SceneObject>();

        internal protected virtual SceneNode InternalCreateSceneNode()
        {
            return new SceneNode(this);
        }

        internal protected virtual SceneNode InternalCreateSceneNode(String node_name)
        {
            return new SceneNode(this, node_name);
        }

        public virtual Light CreateLight(String name, String type)
        {
            Dictionary<String, String> parameters = new Dictionary<String, String>();
            parameters.Add("Type", type);
            return CreateSceneObject(name, "LIGHT", parameters) as Light;
        }

        public virtual Camera CreateCamera(String name, params SceneObjectFilter[] view_filters)
        {
            Dictionary<String, String> parameters = new Dictionary<String, String>();

            if (view_filters != null && view_filters.Count() > 0)
            {
                int filter = 0;
                foreach (SceneObjectFilter object_filter in view_filters)
                    filter |= (int)object_filter;

                parameters.Add("ViewFilter", filter.ToString());
            }

            return CreateSceneObject(name, "CAMERA", parameters) as Camera;
        }

        public virtual StaticMeshEntity CreateStaticMeshEntity(String name, String mesh_name)
        {
            Dictionary<String, String> parameters = new Dictionary<String, String>();
            parameters.Add("MeshName", mesh_name);
            return CreateSceneObject(name, "STATICMESHENTITY", parameters) as StaticMeshEntity;
        }

        public virtual AnimationMeshEntity CreateAnimationMeshEntity(String name, String mesh_name)
        {
            Dictionary<String, String> parameters = new Dictionary<String, String>();
            parameters.Add("MeshName", mesh_name);
            return CreateSceneObject(name, "ANIMATIONMESHENTITY", parameters) as AnimationMeshEntity;
        }

        public virtual SceneObject CreateSceneObject(String name, String type, Dictionary<String, String> parameters)
        {
            SceneObject scene_object = Root.Instance.SceneObjectFactories[type].CreateSceneObject(name, parameters);
            Dictionary<String, SceneObject> scene_objects = GetSceneObjects(type);
            scene_objects.Add(name, scene_object);
            if (scene_object.Is(SceneObjectFilter.HUGE))
                huge_objects.Add(scene_object);
            return scene_object;
        }        

    }
}
